package com.ttg.common.entities;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ttg.common.exception.BaseException;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author ZQ
 * @version 1.0
 * @Description 默认分页
 * @date 2020/12/18 15:06
 */
public class BasePage<T> implements IPage<T> {
    private static final long serialVersionUID = 1870931006788151525L;
    /**
     * 查询数据列表
     */
    private List<T> list = new ArrayList<>();

    /**
     * 排序字段信息
     */
    private List<OrderItem> orders = new ArrayList<>();

    /**
     * 自动优化 COUNT SQL
     */
    private boolean optimizeCountSql = true;
    /**
     * 是否进行 count 查询
     */
    private boolean isSearchCount = true;

    private boolean hitCount = false;
    /**
     * 分页返回参数
     */
    @JsonProperty("pages")
    private PagesRes pagesRes = new PagesRes();

    public BasePage() {

    }

    /**
     * 分页构造函数
     *
     * @param current 当前页
     * @param size    每页显示条数
     */
    public BasePage(long current, long size) {
        this(current, size, 0);
    }

    public BasePage(long current, long size, long total) {
        this(current, size, total, true);
    }

    public BasePage(long current, long size, boolean isSearchCount) {
        this(current, size, 0, isSearchCount);
    }

    public BasePage(long current, long size, long total, boolean isSearchCount) {
        if (current > 1) {
            pagesRes.setPage(current);
        }
        pagesRes.setPagesize(size);
        pagesRes.setTotalnum(total);
        this.isSearchCount = isSearchCount;
        this.hitCount = false;

    }


    @Override
    @JsonIgnore
    public List<T> getRecords() {
        return this.list;
    }

    public List<T> getList() {
        return this.list;
    }


    @JsonIgnore
    public long getTotalPage() {
        if (getSize() == 0) {
            return 0L;
        }
        long pages = getTotal() / getSize();
        if (getTotal() % getSize() != 0) {
            pages++;
        }
        return pages;
    }

    public void setList(List<T> list) {
        this.list = list;
    }

    @Override
    public BasePage<T> setRecords(List<T> records) {
        this.list = records;
        return this;
    }

    @Override
    @JsonIgnore
    public long getTotal() {
        return pagesRes.getTotalnum();
    }

    @Override
    public BasePage<T> setTotal(long total) {
        pagesRes.setTotalnum(total);
        return this;
    }

    @Override
    @JsonIgnore
    public long getSize() {
        return pagesRes.getPagesize();
    }

    @Override
    public BasePage<T> setSize(long size) {
        pagesRes.setPagesize(size);
        return this;
    }

    @Override
    @JsonIgnore
    public long getCurrent() {
        return pagesRes.getPage();
    }

    @Override
    public BasePage<T> setCurrent(long current) {
        pagesRes.setPage(current);
        return this;
    }


    /**
     * 添加新的排序条件
     *
     * @param items 条件
     * @return 返回分页参数本身
     */
    public BasePage<T> addOrder(OrderItem... items) {
        orders.addAll(Arrays.asList(items));
        return this;
    }

    @Override
    public List<OrderItem> orders() {
        return orders;
    }

    @Override
    public boolean optimizeCountSql() {
        return optimizeCountSql;
    }

    @Override
    @JsonIgnore
    public boolean isSearchCount() {
        if (pagesRes.getTotalnum() < 0) {
            return false;
        }
        return isSearchCount;
    }

    public void setSearchCount(boolean isSearchCount) {
        this.isSearchCount = isSearchCount;
    }

    public BasePage<T> setOptimizeCountSql(boolean optimizeCountSql) {
        this.optimizeCountSql = optimizeCountSql;
        return this;
    }
    @Override
    @JsonIgnore
    public void hitCount(boolean hit) {
        this.hitCount = hit;
    }

    @Override
    @JsonIgnore
    public boolean isHitCount() {
        return this.hitCount;
    }

    @Override
    @JsonIgnore
    public long getPages() {
        return getTotalPage();
    }

    public PagesRes getPagesRes() {
        return this.pagesRes;
    }

    public void setPagesRes(PagesRes pagesRes) {
        this.pagesRes = pagesRes;
    }

    /**
     * 类型转换 通过beanCopy
     *
     * @param clazz 转换后的类
     * @param <R>   R
     * @return BasePage
     */
    public <R> BasePage<R> copy(Class<R> clazz) {
        return copy(clazz, obj -> {
            R r = null;
            try {
                r =  clazz.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
                throw new BaseException(e.getMessage());
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                throw new BaseException(e.getMessage());
            }
            BeanUtils.copyProperties(obj, r);
            return r;
        });
    }

    /**
     * 类型转换 通过beanCopy
     *
     * @param clazz 转换后的类
     * @param <R>   R
     * @return BasePage
     */
    public <R> BasePage<R> copy(Class<R> clazz, Function<? super T, ? extends R> mapper) {
        BasePage<R> basePage = new BasePage<>(getCurrent(), getSize(), getTotal(), isSearchCount());
        basePage.setRecords(getRecords().stream().map(mapper).collect(Collectors.toList()));
        return basePage;
    }
}
